package com.weiyi.weiman.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.weiyi.weiman.domain.status.TokenStatus;
import com.weiyi.weiman.exception.TokenException;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import java.util.Random;

/**
 * @Author zhang
 * @Date 2021/5/3 下午3:17
 * @Description jwt工具类
 * @Version 1.0
 **/
@Slf4j
@Component
public class JWTUtils {

    //服务器的kye.用户做加解密的key数据。
    public static String JWT_SECRET = "zXqe!@(_!aa):(\",-)";
    // 通行令牌的过期时间
    private static final long ACCESS_EXPIRE = 12 * 60 * 60 * 1000*100000000;
    // 刷新令牌的过期时间
    private static final long REFRESH_EXPIRE = 72 * 60 * 60 * 1000;

    private static final ObjectMapper MAPPER = new ObjectMapper();

    public static SecretKey generalKey(){
        try {
            byte[] encodedKey=JWT_SECRET.getBytes("UTF-8");
            SecretKey key = new SecretKeySpec(encodedKey,0,encodedKey.length,"AES");
            return key;
        }catch (Exception e){
            e.printStackTrace();
            log.error("jwt密钥初始化失败",e);
        }
        return null;
    }


    /**
     * 签发通行JWT，创建token的方法
     * @param subject  jwt所面向的用户。一般使用用户的登录名
     * @return  token 是为一个用户的有效登录周期准备的一个token 。用户退出或超时，token失效
     */
    public static String createAccessJWT(String subject){
        return createJWT(subject, ACCESS_EXPIRE);
    }

    /**
     * 签发刷新令牌
     * @return
     */
    public static String createRefreshJWT(){
        return createJWT(null, REFRESH_EXPIRE);
    }

    private static String createJWT(String subject, long expire) {
        try {
            SignatureAlgorithm signatureAlgorithm= SignatureAlgorithm.HS256;
            long nowMilllis =System.currentTimeMillis();
            Date now=new Date(nowMilllis);
            SecretKey secretKey=generalKey();
            String id = new Random().nextInt() + "";
            JwtBuilder builder = Jwts.builder()
                    .setId(id)
                    .setSubject(subject)
                    .setIssuedAt(now)   //token生成时间
                    .signWith(signatureAlgorithm,secretKey);//设置密匙和算法
            if (expire > 0){
                long expMillis=nowMilllis + expire;
                Date expDate=new Date(expMillis);
                builder.setExpiration(expDate);
            }
            return builder.compact();
        } catch (Exception e){
            log.error("生成jwt失败",e);
        }
        return null;
    }


    /**
     * 解析JWT字符串
     * @param jwt  就是生成的toekn
     * @return
     */
    public static Claims parseJWT(String jwt){
        SecretKey secretKey=generalKey();
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(jwt)
                .getBody();
    }

    /**
     * 验证jwt
     * @param jwtStr
     * @return
     */
    public static boolean validateJWT(String jwtStr){
        Claims claims = null;
        try {
            //成功
            claims = parseJWT(jwtStr);
            return true;
        } catch (ExpiredJwtException e) {
            //token过期
            throw new TokenException(TokenStatus.TOKEN_EXPIRE);
        } catch (Exception e) {
            throw new TokenException(TokenStatus.TOKEN_ERROR);
        }
    }

    public static String generalSubject(Object subject){
        try {
            return MAPPER.writeValueAsString(subject);
        }catch (Exception e){
            e.printStackTrace();
        }
        return subject+"";
    }

    public static void main(String[] args) {
        String accessJWT = createAccessJWT("1");
        System.out.println(accessJWT);
    }

}